package util

import (
	"reflect"
	"regexp"
	"sync"
	"time"
)

// 判断表名是否合法
func IsValidTableName(name string) bool {
	// 正则校验表名（仅允许字母、数字、下划线）
	return regexp.MustCompile(`^[a-zA-Z0-9_]+$`).MatchString(name)
}

// 判断值是否为空
func IsEmpty(value interface{}) bool {
	if value == nil {
		return true
	}
	v := reflect.ValueOf(value)
	// 解引用指针
	if v.Kind() == reflect.Ptr {
		if v.IsNil() {
			return true
		}
		v = v.Elem()
	}
	// 处理接口
	if v.Kind() == reflect.Interface && !v.IsNil() {
		v = v.Elem()
	}
	// 特殊类型处理
	switch v.Type() {
	case reflect.TypeOf(time.Time{}):
		return v.Interface().(time.Time).IsZero()
	}

	// 根据类型判断空值
	switch v.Kind() {
	case reflect.String, reflect.Array, reflect.Slice, reflect.Map:
		return v.Len() == 0
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Struct:
		// 检查结构体的所有导出字段是否都为空
		t := v.Type()
		for i := 0; i < v.NumField(); i++ {
			if t.Field(i).PkgPath != "" { // 忽略未导出的字段
				continue
			}
			if !IsEmpty(v.Field(i).Interface()) {
				return false
			}
		}
		return true
	default:
		// 其他类型视为非空
		return false
	}
}

// IsSlice 判断是否为切片
func IsSlice(v interface{}) bool {
	value := reflect.ValueOf(v)
	// 检查变量是否为 nil
	if !value.IsValid() {
		return false
	}
	// 检查变量的类型是否为切片
	return value.Kind() == reflect.Slice
}

// IsStruct 判断变量是否为结构体类型
func IsStruct(v any) bool {
	if v == nil {
		return false
	}

	// 获取反射类型对象
	t := reflect.TypeOf(v)

	// 解引用指针（如果是指针类型）
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	// 判断是否为结构体
	return t.Kind() == reflect.Struct
}

// IsScalar 判断是否是标量类型
// 如：数字、布尔、字符串类型
func IsScalar(value interface{}) bool {
	switch value.(type) {
	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, bool, string:
		return true
	default:
		return false
	}
}

// 可比较类型缓存读写锁
var comparableTypeCacheMu sync.RWMutex
var comparableTypeCache = make(map[reflect.Type]bool)

// IsComparable 检查类型是否可比较（带缓存）
func IsComparable(v interface{}) bool {
	if v == nil {
		return false
	}

	// 获取反射类型（处理指针）
	t := reflect.TypeOf(v)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	// 先读取缓存（无需锁）
	comparableTypeCacheMu.RLock()
	result, exists := comparableTypeCache[t]
	comparableTypeCacheMu.RUnlock()

	if exists {
		return result
	}

	// 写入缓存（加锁）
	comparableTypeCacheMu.Lock()
	defer comparableTypeCacheMu.Unlock()

	// 双重检查，避免并发写入
	if result, exists = comparableTypeCache[t]; exists {
		return result
	}

	// 计算并缓存结果
	result = t.Comparable()
	comparableTypeCache[t] = result
	return result
}
